% File: ECMI01.FF_MAIN % Author: Peter Hammond, IC, 1982. Rewritten by Peter Ross % Updated: 30 Nov 1983 % Purpose: FAULFINDER's top level % Top level, after using ffload/1 from 'load' to set up a database, is % find_fault/0. find_fault :- initialise, prompt(Old, '..? '), writef('The system will ask you some questions about your problem.\l'), explain_replies, nl, nl, top_fault(Name), find_out(Name, State, [find_fault]), describe(Name, State). find_fault :- \+ top_fault(_), writef('You haven''t read in a specific description file, sunshine.\l'), writef('Use ffload(File) to read one (e.g. ecmi01.ff_gasheater).\l'). initialise :- erase_old(fact, state(Fault, State)). describe(Fault, State) :- recorded(Fault, name(FullName), _), writef('The original fault, %w, ', [FullName]), give_state(State). % 'find_out' finds the final state of a fault. This is the meaty bit. find_out(Fault, State, History) :- check_preconditions(Fault, History), check_for(Fault, ApparentState, History), deduce(Fault, State, History). % 'check_preconditions' investigates any preconditions a fault may have check_preconditions(Fault, _) :- recorded(Fault, preconditions(none), _). check_preconditions(Fault, History) :- recorded(Fault, preconditions(not(P)), _), find_out(P, State, [check_preconditions(Fault)|History]), check_not_precond(State, Fault). check_not_precond(cannot_exist, _) :- !. check_not_precond(corrected, _) :- !. check_not_precond(cannot_be_corrected, Fault) :- add_fact(F, cannot_exist). % 'check_for' determines the current state of a fault: whether it is % already known, or if the user must be asked check_for(Fault, State, History) :- know(Fault, State), !. check_for(Fault, State, History) :- ask_for_apparent(Fault, State, History). ask_for_apparent(Fault, State, History) :- recorded(Fault, question(Query), _), recorded(Fault, confirm(ExpectedAns), _), writef('%w?\l', [Query]), read_ans(ActualAns, [ask_for_apparent(Fault,State)|History]), use_ans(ActualAns, ExpectedAns, State), add_fact(Fault, State). use_ans(Ans, Ans, exists). use_ans(dunno, _, may_exist). use_ans(Ans, OtherAns, cannot_exist) :- opposite_ans(Ans, OtherAns). % 'deduce' decides whether the rules must be consulted to find the % state of a fault deduce(Fault, State, _) :- know(Fault, State), memberchk(State, [cannot_be_corrected, cannot_exist, corrected]). deduce(Fault, State, History) :- (know(Fault, may_exist) ; know(Fault, exists)), check_rules_for(Fault, State, History). check_rules_for(Fault, State, History) :- recorded(Fault, type(Type), _), check_rule(Type, Fault, History), know(Fault, State).