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

```