% File: /usr/lib/prolog/teach/faultfiner/rules % Author: Peter hammond, IC, 1982. Rewritten by Peter Ross % Updated: 30 Nov 1983 % Purpose: the guts of FAULTFINDER. % The only export is check_rule/3. This finds the final state % of a fault by working recursively through the causes, and their % causes... check_rule(general, Fault, History) :- check_causes_of(Fault, History). check_rule(specific, Fault, History) :- suggest_action_for(Fault), check_again_for(Fault, History). check_rule(separable, Fault, History) :- suggest_action_for(Fault), test_action_for(Fault, Ans, History), pursue_causes_of(Fault, Ans, History). % *********************** % * Machinery for rules * % *********************** check_causes_of(Fault, History) :- recorded(Fault, causes(PossCauses), _), check_causes(Fault, PossCauses, PossCauses, History). suggest_action_for(Fault) :- recorded(Fault, action(Action), _), writef('%w.\l', [Action]). test_action_for(Fault, Ans, History) :- recorded(Fault, test(Test), _), writef('%w?\l', [Test]), read_ans(Ans, [test_action_for(Fault, Ans)|History]). pursue_causes_of(Fault, Ans, History) :- recorded(Fault, decisions(List), _), memberchk(PossCauses if Ans, List), check_causes(Fault, PossCauses, PossCauses, History). check_causes(Fault, Cause or MoreCauses, AllCauses, History) :- check_one_cause(Fault, Cause, History) ; check_causes(Fault, MoreCauses, AllCauses, History). check_causes(Fault, LastCause, AllCauses, History) :- check_one_cause(Fault, LastCause, History) ; recorded(Fault, name(FullNameOfFault), _), writef('There are no more causes to check, for\l\t%w\l', [FullNameOfFault]), check_again_causes(Fault, AllCauses). check_one_cause(Fault, Cause, History) :- once(find_out(Cause, State, [check_one_cause(Fault,Cause)|History])), use_cause_state(Fault, Cause, State, [check_one_cause(Fault, Cause)|History]). use_cause_state(Fault, Cause, cannot_exist, _) :- fail. use_cause_state(Fault, Cause, cannot_be_corrected, History) :- add_fact(Fault, cannot_be_corrected), ask_to_proceed_with(Fault, Cause, cannot_be_corrected, History). use_cause_state(Fault, Cause, corrected, History) :- ask_to_proceed_with(Fault, Cause, corrected, History). ask_to_proceed_with(Fault, Cause, StateOfCause, History) :- once(inform_position(Fault, Cause, StateOfCause)), check_proceed_answer(Fault, StateOfCause, History). check_proceed_answer(Fault, cannot_be_corrected, History) :- recorded(Fault, name(FullName), _), writef('Do you want to go on investigating the fault\l\t%w?\l', [FullName]), once(read_ans(Ans, [check_proceed_answer(Fault, cannot_be_corrected)|History])), Ans = no. check_proceed_answer(Fault, corrected, History) :- query_again(Fault, ExpectedAns), once(read_ans(ActualAns, [check_proceed_answer(Fault, corrected)|History])), use_proceed_ans(ActualAns, ExpectedAns, Fault). use_proceed_ans(ActualAns, ExpectedAns, Fault) :- opposite_ans(ActualAns, ExpectedAns), add_fact(Fault, corrected). query_again(Fault, ExpectedAns) :- recorded(Fault, question(Query), _), recorded(Fault, confirm(ExpectedAns), _), writef('%w now?\l', [Query]). check_again_causes(Fault, AllCauses) :- ( know(Fault, cannot_be_corrected) ; all_causes_in_same_state(Fault, AllCauses) ; mixture_of_causes_of(Fault) ). all_causes_in_same_state(Fault, AllCauses) :- know_all(AllCauses, State), use_all_causes_state(Fault, State). know_all(Cause or MoreCauses, State) :- !, know(Cause, State), know_all(MoreCauses, State). know_all(LastCause, State) :- know(LastCause, State). use_all_causes_state(Fault, cannot_exist) :- know(Fault, exists) -> use_all_causes_state(Fault, corrected) ; add_fact(Fault, cannot_exist). use_all_causes_state(Fault, corrected) :- add_fact(Fault, cannot_be_corrected), recorded(Fault, name(FullName), _), writef('Model does not include correction of fault\l\t%w\l', [FullName]). mixture_of_causes_of(Fault) :- use_all_causes_state(Fault, corrected). inform_position(Fault, Cause, StateOfCause) :- recorded(Fault, name(FullNameOfFault), _), recorded(Cause, name(FullNameOfCause), _), writef('The fault being investigated is\l\t%w.\l', [FullNameOfFault]), writef('One possible cause is\l\t%w\lwhich ', [FullNameOfCause]), give_state(StateOfCause). give_state(cannot_be_corrected) :- writef('cannot be corrected.\l'). give_state(corrected) :- writef('has now been corrected.\l'). give_state(cannot_exist) :- writef('cannot exist.\l'). check_again_for(Fault, History) :- query_again(Fault, ExpectedAns), read_ans(ActualAns, [check_again_for(Fault)|History]), use_action_ans(Fault, ActualAns, ExpectedAns). use_action_ans(Fault, ActualAns, ExpectedAns) :- opposite_ans(ActualAns, ExpectedAns) -> add_fact(Fault, corrected) ; add_fact(Fault, cannot_be_corrected).