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) .