## Source Code: Bayesian Belief Network

### FRAUD.KSL Listing

/* Bayesian Belief Network Example - Charles Langley May 2002 ========================================================== Modified for WebFlex May 2002 Alan Westwood This example demonstrates the use of forward-chaining uncertainty rules in a motor insurance fraud detection problem. Description ----------- The example implements a probablistic fraud detection expert system. The problem is tackled in four distinct stages: 1. Initialise fraud indicators to their a priori probabilities. 2. Ask the user for indicator probabilities, either from a list of yes, no and not_known or by means of a number between 0 (false) and 1 (true). 3. Calculate the overall probability of fraud using Bayesian updating. 4. Carry out hypothetical reasoning to see what unknown indicators would be worth investigating (if any). Running the Example ------------------- The top-level goal to run the expert system is start/0. This can be invoked by entering the following goal at the console: ?- run. Flex Technical Points --------------------- The following flex technical points are demonstrated in this example: 1. The use of questions to elicit user input. 2. The use of affirms and denies weights in calculating probabilities. 3. The use of a simple set of frames to store the probabilities. 4. Frame instances and attribute inheritance. 5. The implicit representation of a Bayesian Belief Network in both a structured rulebase and a frame hierarchy. The Bayesian Belief Network --------------------------- Both the frame hierarchy and the structure of the set of rules in 'group ruleset' encode the following Bayesian Belief Network: === === ==== === === === fi8 fi9 fi10 fi4 fi1 fi2 === === ==== === === === \ / | \ / \ / | | | | v | v v === | === === i-1 | i-2 i-3 === | === === \ | \ / \ | \ / v v v v ======== ========== staged non event disclosure ======== ========== \ / \ / v v ===== fraud ===== */ action run; do restart and ask questions and write(`You answered that:<br><br><blockquote>`) and initialise_indicators and update_indicators and check that {P1,NotP1} is f_indicator_8`s posterior_prob_list and check that {P2,NotP2} is f_indicator_9`s posterior_prob_list and check that {P3,NotP3} is f_indicator_10`s posterior_prob_list and check that {P4,NotP4} is f_indicator_4`s posterior_prob_list and check that {P5,NotP5} is f_indicator_1`s posterior_prob_list and check that {P6,NotP6} is f_indicator_2`s posterior_prob_list and check that {I1,NotI1} is intermediate_1`s posterior_prob_list and check that {I2,NotI2} is intermediate_2`s posterior_prob_list and check that {I3,NotI3} is intermediate_3`s posterior_prob_list and check that {S,NotS} is staged_event`s posterior_prob_list and check that {ND,NotND} is non_disclosure`s posterior_prob_list and check that {F,NotF} is fraud`s posterior_prob_list and fire(P1,P2,P3,P4,P5,P6,I1,I2,I3,S,ND,F) and check that {NewS,NotNewS} is staged_event`s posterior_prob_list and staged_event`s percent becomes NewS * 100 // 1 and write(`<//blockquote><br>On the basis of this evidence we calculate that:<br><br>`) and write(`<b>The probability of a staged event is `) and write(staged_event`s percent) and write(` %<br>`) and check that {NewND,NotNewND} is non_disclosure`s posterior_prob_list and non_disclosure`s percent becomes NewND * 100 // 1 and write(`The probability of non disclosure is `) and write(non_disclosure`s percent) and write(` %<br>`) and check that {P,NotP} is fraud`s posterior_prob_list and write(`<br>The probability of fraud is `) and fraud`s percent becomes P * 100 // 1 and write(fraud`s percent) and write(` %<//b><br><br>`) and what_next(P) and make_suggestion . frame node . frame probability_node is a node default inlink_list is {} and default outlink_list is {} and default prior_prob_list is {0.25,0.75} and default posterior_prob_list is {0.25,0.75} and default percent is 25 . instance f_indicator_8 is a probability_node description is `FI8: Recovered burnt out or accident damaged` and inlink_list is {} and outlink_list is {intermediate_1} and posterior_prob_list is {0.1,0.9} and prior_prob_list is {0.1,0.9} . instance f_indicator_9 is a probability_node description is `FI9: Reg Mark 'S' or newer` and inlink_list is {} and outlink_list is {intermediate_1} and posterior_prob_list is {0.1,0.9} and prior_prob_list is {0.1,0.9} . instance f_indicator_10 is a probability_node description is `FI10: Too cut and dried, pushing TP claim` and inlink_list is {} and outlink_list is {intermediate_2,staged_event} and posterior_prob_list is {0.1,0.9} and prior_prob_list is {0.1,0.9} . instance f_indicator_4 is a probability_node description is `FI4: Not satisfied with client's response` and inlink_list is {} and outlink_list is {intermediate_2} and posterior_prob_list is {0.2,0.8} and prior_prob_list is {0.2,0.8} . instance f_indicator_1 is a probability_node description is `FI1: Claim made within 1 month of inception` and inlink_list is {} and outlink_list is {intermediate_3} and posterior_prob_list is {0.05,0.95} and prior_prob_list is {0.05,0.95} . instance f_indicator_2 is a probability_node description is `FI2: 4 or more claims made within any year` and inlink_list is {} and outlink_list is {intermediate_3} and posterior_prob_list is {0.15,0.85} and prior_prob_list is {0.15,0.85} . instance intermediate_1 is a probability_node inlink_list is {f_indicator_8,f_indicator_9} and outlink_list is {staged_event} . instance intermediate_2 is a probability_node inlink_list is {f_indicator_10,f_indicator_4} and outlink_list is {non_disclosure} . instance intermediate_3 is a probability_node inlink_list is {f_indicator_1,f_indicator_2} and outlink_list is {non_disclosure} . instance staged_event is a probability_node inlink_list is {intermediate_1,f_indicator_10} and outlink_list is {fraud} and prior_prob_list is {0.2,0.8} and posterior_prob_list is {0.2,0.8} . instance non_disclosure is a probability_node inlink_list is {intermediate_2,intermediate_3} and outlink_list is {fraud} and prior_prob_list is {0.4,0.6} and posterior_prob_list is {0.4,0.6} . instance fraud is a probability_node inlink_list is {staged_event,non_disclosure} and outlink_list is {} and prior_prob_list is {0.1,0.9} and posterior_prob_list is {0.1,0.9} . frame hypothetical default indicator is none and default description is `unknown indicator` and default probability_of_fraud is 0 and default percent is 0 . instance current_hypothetical is a hypothetical . group ruleset rf_indicator_8_1, rf_indicator_9_1, rf_indicator_10_1, rf_indicator_10_2, rf_indicator_4_1, rf_indicator_1_1, rf_indicator_2_1, rintermediate_1_1, rintermediate_2_1, rintermediate_3_1, rstaged_event_1, rnon_disclosure_1 . uncertainty_rule rf_indicator_8_1 if f_indicator_8 is yes (affirms 5.62500 ; denies 0.11905) then intermediate_1 is yes . uncertainty_rule rf_indicator_9_1 if f_indicator_9 is yes (affirms 4.41176 ; denies 0.30120) then intermediate_1 is yes . uncertainty_rule rf_indicator_10_1 if f_indicator_10 is yes (affirms 5.62500 ; denies 0.11905) then intermediate_2 is yes . uncertainty_rule rf_indicator_10_2 if f_indicator_10 is yes (affirms 6.07692 ; denies 0.24138) then staged_event is yes . uncertainty_rule rf_indicator_4_1 if f_indicator_4 is yes (affirms 4.41176 ; denies 0.30120) then intermediate_2 is yes . uncertainty_rule rf_indicator_1_1 if f_indicator_1 is yes (affirms 5.62500 ; denies 0.11905) then intermediate_3 is yes . uncertainty_rule rf_indicator_2_1 if f_indicator_2 is yes (affirms 4.41176 ; denies 0.30120) then intermediate_3 is yes . uncertainty_rule rintermediate_1_1 if intermediate_1 is yes (affirms 18.50000 ; denies 0.07895) then staged_event is yes . uncertainty_rule rintermediate_2_1 if intermediate_2 is yes (affirms 105.55556 ; denies 0.05045) then non_disclosure is yes . uncertainty_rule rintermediate_3_1 if intermediate_3 is yes (affirms 97.00000 ; denies 0.03030) then non_disclosure is yes . uncertainty_rule rstaged_event_1 if staged_event is yes (affirms 95.00000 ; denies 0.05051) then fraud is yes . uncertainty_rule rnon_disclosure_1 if non_disclosure is yes (affirms 60.00000 ; denies 0.10152) then fraud is yes . relation fire(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12) if reset all probability values and the probability that f_indicator_8 is yes = P1 and the probability that f_indicator_9 is yes = P2 and the probability that f_indicator_10 is yes = P3 and the probability that f_indicator_4 is yes = P4 and the probability that f_indicator_1 is yes = P5 and the probability that f_indicator_2 is yes = P6 and the probability that intermediate_1 is yes = P7 and the probability that intermediate_2 is yes = P8 and the probability that intermediate_3 is yes = P9 and the probability that staged_event is yes = P10 and the probability that non_disclosure is yes = P11 and the probability that fraud is yes = P12 and propagate ruleset probability rules and the probability that f_indicator_8 is yes = P1a and the probability that f_indicator_9 is yes = P2a and the probability that f_indicator_10 is yes = P3a and the probability that f_indicator_4 is yes = P4a and the probability that f_indicator_1 is yes = P5a and the probability that f_indicator_2 is yes = P6a and the probability that intermediate_1 is yes = P7a and the probability that intermediate_2 is yes = P8a and the probability that intermediate_3 is yes = P9a and the probability that staged_event is yes = P10a and the probability that non_disclosure is yes = P11a and update_ProbH(f_indicator_8,P1a) and update_ProbH(f_indicator_9,P2a) and update_ProbH(f_indicator_10,P3a) and update_ProbH(f_indicator_4,P4a) and update_ProbH(f_indicator_1,P5a) and update_ProbH(f_indicator_2,P6a) and update_ProbH(intermediate_1,P7a) and update_ProbH(intermediate_2,P8a) and update_ProbH(intermediate_3,P9a) and update_ProbH(staged_event,P10a) and update_ProbH(non_disclosure,P11a) and the probability that fraud is yes = P12a and update_ProbH(fraud,P12a) . action initialise_probability(N) do global`s new_prior_prob_list becomes N`s prior_prob_list and N`s posterior_prob_list becomes global`s new_prior_prob_list . %-------------------------------------------------------------------------- relation make_suggestion if current_hypothetical`s indicator is not none and current_hypothetical`s percent becomes current_hypothetical`s probability_of_fraud * 100 // 1 and write( `<b>` ) and write(`Suggestion: investigate if `) and write(current_hypothetical`s description) and write(` is true.<br>`) and write(`Because if it is, the probability of fraud would be `) and write(current_hypothetical`s percent) and write(` %<br><//b>`) . relation make_suggestion . relation update(Node,Value) if Value is yes and write(`The probability of `) and write(Node`s description) and write(` is 100 %<br>`) and update_ProbH(Node,1) . relation update(Node,Value) if Value is no and write(`The probability of `) and write(Node`s description) and write(` is 0 %<br>`) and update_ProbH(Node,0) . relation update(Node,Value) if Value >= 0 and Value =< 1 and write(`The probability of `) and write(Node`s description) and write(` is `) and write(Value*100) and write(` %<br>`) and update_ProbH(Node,Value) . relation update(Node,Value) if Value is not_known and check Node`s prior_prob_list is {Prior,_} and write(`The probability of `) and write(Node`s description) and write(` is not known.<br>`) and update_ProbH(Node,Prior) . group questions fi8, fi9, fi10, fi4, fi1, fi2 . frame questions_style ; default body is 'fraud1.htm' and default columns is 2 and default caption is 'Enter the details of the claim' and default tablestyle is { bgcolor-'#ffffcc', cellpadding-10, border-0 } . frame radio_style ; default rows is 3 and default method is radio . frame fi1_style is a radio_style . frame fi2_style is a radio_style . frame fi8_style is a radio_style . frame fi9_style is a radio_style . frame fi4_style ; default prefill is 0.5 and default lower_bound is 0 and default upper_bound is 1 . frame fi10_style ; default prefill is 0.5 and default lower_bound is 0 and default upper_bound is 1 . question fi8 'Was the car recovered burnt out, damaged?'; choose from yes, not_known, no; because The client might have done it himself . question fi9 'Was the car S registration or later?'; choose from yes, not_known, no; because The car should then have security locking . question fi10 'Was the client too cut and dried pushing third party claim? (0-1)'; input number because The event may be staged . question fi4 'Were you disatisfied with the response of the client? (0-1)'; input number because That is suspicious . question fi1 'Claim within one month of inception?'; choose from yes, not_known, no because The policy may have been taken out for fraud . question fi2 'Were there 4 or more claims in one year?'; choose from yes, not_known, no; because In combination with other circumstances, this is a possible indicator of fraud . relation not_known(Indicator) if check that Indicator`s posterior_prob_list is {PostTrue,PostFalse} and check that Indicator`s prior_prob_list is {PriorTrue,PriorFalse} and z becomes PostTrue - PriorTrue and z < 0.0000000001 and z > -0.0000000001 . action what_next(OldF) ; do for every Indicator is some instance of probability_node and Indicator`s inlink_list is {} and not_known(Indicator) do tryout(Indicator) and initialise_probability(Indicator) and fraud`s posterior_prob_list becomes {OldF,1 - OldF} end for . relation tryout(Indicator) if Indicator`s posterior_prob_list becomes {1,0} and check that fraud`s posterior_prob_list is {OldF,_} and fraud`s posterior_prob_list becomes fraud`s prior_prob_list and intermediate_1`s posterior_prob_list becomes intermediate_1`s prior_prob_list and intermediate_2`s posterior_prob_list becomes intermediate_2`s prior_prob_list and intermediate_3`s posterior_prob_list becomes intermediate_3`s prior_prob_list and staged_event`s posterior_prob_list becomes staged_event`s prior_prob_list and non_disclosure`s posterior_prob_list becomes non_disclosure`s prior_prob_list and check that {P1,NotP1} is f_indicator_8`s posterior_prob_list and check that {P2,NotP2} is f_indicator_9`s posterior_prob_list and check that {P3,NotP3} is f_indicator_10`s posterior_prob_list and check that {P4,NotP4} is f_indicator_4`s posterior_prob_list and check that {P5,NotP5} is f_indicator_1`s posterior_prob_list and check that {P6,NotP6} is f_indicator_2`s posterior_prob_list and check that {I1,NotI1} is intermediate_1`s posterior_prob_list and check that {I2,NotI2} is intermediate_2`s posterior_prob_list and check that {I3,NotI3} is intermediate_3`s posterior_prob_list and check that {S,NotS} is staged_event`s posterior_prob_list and check that {ND,NotND} is non_disclosure`s posterior_prob_list and check that {F,NotF} is fraud`s posterior_prob_list and fire(P1,P2,P3,P4,P5,P6,I1,I2,I3,S,ND,F) and check that {NewF,NewNotF} is fraud`s posterior_prob_list and NewF > OldF and NewF > 0.45 and NewF - OldF > 0.01 and update_hypothetical(Indicator,NewF) . relation tryout(Indicator) . relation update_ProbH(Node,NewProbH) if Node is an instance of probability_node and global`s newProbNotH becomes 1 - NewProbH and Node`s posterior_prob_list becomes {NewProbH,newProbNotH} . relation update_hypothetical(Indicator,Probability_of_fraud) if current_hypothetical`s probability_of_fraud is less than Probability_of_fraud and current_hypothetical`s indicator becomes Indicator and current_hypothetical`s description becomes Indicator`s description and current_hypothetical`s probability_of_fraud becomes Probability_of_fraud . relation update_hypothetical(Indicator,Proability_of_fraud) . relation initialise_indicators if initialise_probability(f_indicator_8) and initialise_probability(f_indicator_9) and initialise_probability(f_indicator_10) and initialise_probability(f_indicator_4) and initialise_probability(f_indicator_1) and initialise_probability(f_indicator_2) and initialise_probability(intermediate_1) and initialise_probability(intermediate_2) and initialise_probability(intermediate_3) and initialise_probability(staged_event) and initialise_probability(non_disclosure) and initialise_probability(fraud) . relation update_indicators if update(f_indicator_8,fi8) and update(f_indicator_9,fi9) and update(f_indicator_10,fi10) and update(f_indicator_4,fi4) and update(f_indicator_1,fi1) and update(f_indicator_2,fi2) .